from typing import Dict, Callable, List
from new_rmasm import utils

# ======================
#      宏命令转换器
# ======================


# key 是宏的名字
# 参数是 宏所属者 和 参数列表(list)
macro_command_translators: Dict['str', Callable[[str, List[str]], str]] = {}


def macro_command_translator(name):
    def wrapper(func):
        macro_command_translators[name] = func
        return func

    return wrapper


@macro_command_translator('comment')
def mact_raw(obj: str, args: List[str]) -> str:
    yield '#'
    for i in mact_raw(obj, args):
        yield i


@macro_command_translator('raw')
def mact_raw(obj: str, args: List[str]) -> str:
    for a in args:
        if not isinstance(a, str):
            yield a
        elif utils.is_string(a):
            yield a[1:-1]
        else:
            yield a


@macro_command_translator('write')
def mact_write(obj: str, args: List[str]) -> str:
    return f'write {args[1]} {obj} {args[0]}'


@macro_command_translator('draw_clear')
def mact_draw_clear(obj: str, args: List[str]) -> str:
    if len(args) == 1:
        return f'draw clear {args[0]} {args[0]} {args[0]}'
    return f'draw clear {args[0]} {args[1]} {args[2]}'


@macro_command_translator('draw_color')
def mact_draw_color(obj: str, args: List[str]) -> str:
    if len(args) == 1:
        return f'draw color {args[0]} {args[0]} {args[0]} 255'
    if len(args) == 3:
        return f'draw color {args[0]} {args[1]} {args[2]} 255'
    return f'draw color {args[0]} {args[1]} {args[2]} {args[3]}'


@macro_command_translator('draw_stroke')
def mact_draw_stroke(obj: str, args: List[str]) -> str:
    return f'draw stroke {args[0]}'


@macro_command_translator('draw_line')
def mact_draw_line(obj: str, args: List[str]) -> str:
    return f'draw line {args[0]} {args[1]} {args[2]} {args[3]}'


@macro_command_translator('draw_rect')
def mact_draw_rect(obj: str, args: List[str]) -> str:
    return f'draw rect {args[0]} {args[1]} {args[2]} {args[3]}'


@macro_command_translator('draw_line_rect')
def mact_draw_line_rect(obj: str, args: List[str]) -> str:
    return f'draw lineRect {args[0]} {args[1]} {args[2]} {args[3]}'


@macro_command_translator('draw_poly')
def mact_draw_poly(obj: str, args: List[str]) -> str:
    if obj:
        args = args.copy()
        args.insert(2, obj)
    if len(args) == 4:
        return f'draw poly {args[0]} {args[1]} {args[2]} {args[3]} 0'
    return f'draw poly {args[0]} {args[1]} {args[2]} {args[3]} {args[4]}'


@macro_command_translator('draw_line_poly')
def mact_draw_line_poly(obj: str, args: List[str]) -> str:
    if obj:
        args = args.copy()
        args.insert(2, obj)
    if len(args) == 4:
        return f'draw linePoly {args[0]} {args[1]} {args[2]} {args[3]} 0'
    return f'draw linePoly {args[0]} {args[1]} {args[2]} {args[3]} {args[4]}'


@macro_command_translator('draw_triangle')
def mact_draw_triangle(obj: str, args: List[str]) -> str:
    return f'draw triangle {args[0]} {args[1]} {args[2]} {args[3]} {args[4]} {args[5]}'


@macro_command_translator('draw_image')
def mact_draw_image(obj: str, args: List[str]) -> str:
    if obj:
        args = args.copy()
        args.insert(2, obj)
    if len(args) == 4:
        return f'draw image {args[0]} {args[1]} {args[2]} {args[3]} 0'
    return f'draw image {args[0]} {args[1]} {args[2]} {args[3]} {args[4]}'


@macro_command_translator('draw_flush')
def mact_print_flush(obj: str, args: List[str]) -> str:
    return f'drawflush {args[0]}'


@macro_command_translator('print')
def mact_print(obj: str, args: List[str]) -> str:
    return f'print {args[0]}'


@macro_command_translator('print_flush')
def mact_print_flush(obj: str, args: List[str]) -> str:
    return f'printflush {args[0]}'


@macro_command_translator('shoot')
def mact_shoot(obj: str, args: List[str]) -> str:
    args = args.copy()
    if len(args) == 2:
        args.append('1')
    return f'control shoot {obj} {args[0]} {args[1]} {args[2]}'


@macro_command_translator('enabled')
def mact_enabled(obj: str, args: List[str]) -> str:
    return f'control enabled {obj} {args[0]}'


@macro_command_translator('shootp')
def mact_shootp(obj: str, args: List[str]) -> str:
    args = args.copy()
    if len(args) == 1:
        args.append('1')
    return f'control shootp {obj} {args[0]} {args[1]}'


@macro_command_translator('config')
def mact_config(obj: str, args: List[str]) -> str:
    return f'control config {obj} {args[0]}'


@macro_command_translator('color')
def mact_color(obj: str, args: List[str]) -> str:
    if len(args) == 1:
        return f'control color {obj} {args[0]} {args[0]} {args[0]}'
    return f'control color {obj} {args[0]} {args[1]} {args[2]}'


@macro_command_translator('wait')
def mact_wait(obj: str, args: List[str]) -> str:
    return f'wait {args[0]}'


@macro_command_translator('$')
def mact_ubind(obj: str, args: List[str]) -> str:
    return f'ubind {args[0]}'


@macro_command_translator('$idle')
def mact_ucontrol_idle(obj: str, args: List[str]) -> str:
    return f'ucontrol idle'


@macro_command_translator('$stop')
def mact_ucontrol_stop(obj: str, args: List[str]) -> str:
    return f'ucontrol stop'


@macro_command_translator('$move')
def mact_ucontrol_move(obj: str, args: List[str]) -> str:
    return f'ucontrol move {args[0]} {args[1]}'


@macro_command_translator('$approach')
def mact_ucontrol_approach(obj: str, args: List[str]) -> str:
    return f'ucontrol approach {args[0]} {args[1]} {args[2]}'


@macro_command_translator('$boost')
def mact_ucontrol_boost(obj: str, args: List[str]) -> str:
    return f'ucontrol boost {args[0]}'


@macro_command_translator('$pathfind')
@macro_command_translator('$path_find')
def mact_ucontrol_path_find(obj: str, args: List[str]) -> str:
    return f'ucontrol pathfind'


@macro_command_translator('$target')
def mact_ucontrol_target(obj: str, args: List[str]) -> str:
    args = args.copy()
    if len(args) == 2:
        args.append('1')
    return f'ucontrol target {args[0]} {args[1]} {args[2]}'


@macro_command_translator('$targetp')
def mact_ucontrol_targetp(obj: str, args: List[str]) -> str:
    args = args.copy()
    if len(args) == 1:
        args.append('1')
    return f'ucontrol targetp {args[0]} {args[1]}'


@macro_command_translator('$item_drop')
def mact_ucontrol_item_drop(obj: str, args: List[str]) -> str:
    return f'ucontrol itemDrop {args[0]} {args[1]}'


@macro_command_translator('$item_take')
def mact_ucontrol_item_take(obj: str, args: List[str]) -> str:
    args = args.copy()
    if obj:
        args.insert(0, obj)
    return f'ucontrol itemTake {args[0]} {args[1]} {args[2]}'


@macro_command_translator('$pay_drop')
def mact_ucontrol_pay_drop(obj: str, args: List[str]) -> str:
    return f'ucontrol payDrop'


@macro_command_translator('$pay_take')
def mact_ucontrol_pay_take(obj: str, args: List[str]) -> str:
    return f'ucontrol payTake {args[0]}'


@macro_command_translator('$pay_enter')
def mact_ucontrol_pay_enter(obj: str, args: List[str]) -> str:
    return f'ucontrol payEnter'


@macro_command_translator('$mine')
def mact_ucontrol_mine(obj: str, args: List[str]) -> str:
    return f'ucontrol mine {args[0]} {args[1]}'


@macro_command_translator('$flag')
def mact_ucontrol_flag(obj: str, args: List[str]) -> str:
    return f'ucontrol flag {args[0]}'


@macro_command_translator('$build')
def mact_ucontrol_build(obj: str, args: List[str]) -> str:
    args = args.copy()
    if obj:
        args.insert(2, obj)
    if len(args) == 3:
        args.append('0')
    if len(args) == 4:
        args.append('0')
    return f'ucontrol build {args[0]} {args[1]} {args[2]} {args[3]} {args[4]}'


@macro_command_translator('$get_block')
def mact_ucontrol_get_block(obj: str, args: List[str]) -> str:
    return f'ucontrol getBlock {args[0]} {args[1]} {args[2]} {args[3]}'


@macro_command_translator('$within')
def mact_ucontrol_within(obj: str, args: List[str]) -> str:
    return f'ucontrol within {args[0]} {args[1]} {args[2]} {args[3]}'


@macro_command_translator('$locate_ore')
@macro_command_translator('$find_ore')
def mact_ucontrol_find_ore(obj: str, args: List[str]) -> str:
    args = args.copy()
    if len(args) == 1:
        args.append('outx')
        args.append('outy')
        args.append('found')
    return \
        f'ulocate ore core true {args[0]} {args[1]} {args[2]} {args[3]} building'


@macro_command_translator('$locate_building')
@macro_command_translator('$find_building')
def mact_ucontrol_find_building(obj: str, args: List[str]) -> str:
    args = args.copy()
    if len(args) == 2:
        args.append('outx')
        args.append('outy')
        args.append('found')
        args.append('building')
    return \
        f'ulocate building {args[0]} {args[1]} @copper {args[2]} {args[3]} {args[4]} {args[5]}'


@macro_command_translator('$locate_spawn')
@macro_command_translator('$find_spawn')
def mact_ucontrol_find_spawn(obj: str, args: List[str]) -> str:
    args = args.copy()
    if len(args) == 0:
        args.append('outx')
        args.append('outy')
        args.append('found')
        args.append('building')
    return \
        f'ulocate spawn core true @copper {args[0]} {args[1]} {args[2]} {args[3]}'


@macro_command_translator('$locate_damaged')
@macro_command_translator('$find_damaged')
def mact_ucontrol_find_damaged(obj: str, args: List[str]) -> str:
    args = args.copy()
    if len(args) == 0:
        args.append('outx')
        args.append('outy')
        args.append('found')
        args.append('building')
    return \
        f'ulocate damaged core true @copper {args[0]} {args[1]} {args[2]} {args[3]}'
